package com.knowledge.share.utils;

import cn.hutool.core.io.FileUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.knowledge.share.config.AliOssProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import java.util.UUID;

@Slf4j
@Component
public class FileTools {

    @Autowired
    private AliOssProperties aliOSSProperties;
    /**
     * @desc 生成随机得文件名得方法
     * @param file
     * @return
     */
    public static String randomFileName(MultipartFile file){
        //获取保存文件的路径信息,处理文件名逻辑
        //获取文件的原始名字，整体文件名字包含后缀的
        String originalFilename = file.getOriginalFilename();
        //获取文件后缀名的下标的值
        int index = originalFilename.lastIndexOf(".");
        //获取文件的前缀名字
        String suffix = originalFilename.substring(0,index);
        //文件后缀的名字信息
        String extName = originalFilename.substring(index);
        //拼接字符串的信息
        originalFilename = UUID.randomUUID().toString()+"_"+suffix+extName;

        return originalFilename;
    }

    /**
     * @desc 文件上传到OSS服务上去
     * @param file
     * @return
     */
    public String uploadOss(MultipartFile file){
        //定义Url得地址
        String url = "";

        //获取Aliyun得配置信息得内容
        String endpoint = aliOSSProperties.getEndpoint();
        String accessKeyId = aliOSSProperties.getAccessKeyId();
        String bucketName = aliOSSProperties.getBucketName();
        String accessKeySecret = aliOSSProperties.getAccessKeySecret();

        try{
            // 获取上传的文件的输入流
            InputStream inputStream = file.getInputStream();

            //自动生成文件名的方法逻辑
            String fileName = FileTools.randomFileName(file);
            //上传文件到 OSS
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.putObject(bucketName, fileName, inputStream);
            //文件访问路径
            url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
            log.info("生成的文件名是:{}",url);
            // 关闭ossClient
            ossClient.shutdown();
        }catch (IOException e){
            e.printStackTrace();
        }

        return url;
    }


    /**
     * @desc 执行文件合并的逻辑操作对象信息，执行文件合并的逻辑操作
     * @param tmpFolder
     * @param targetFileName
     * @param fileName
     * @param isDel
     */
    public static void unionFile(String tmpFolder,String targetFileName,String fileName,Boolean isDel) throws Exception {
        log.info("临时目录:{},目标文件夹:{},文件名:{}",tmpFolder,targetFileName,fileName);

        File tmpDir = new File(tmpFolder);
        if(!tmpDir.exists()){
            throw new Exception("临时目录不存在");
        }

        //获取临时目录下的所有文件对象
        File[] listFiles = tmpDir.listFiles();
        //把切片文件夹按照切片数字大小从小向大排序,升序排列
        Arrays.sort(listFiles, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                Integer value1 = Integer.valueOf(o1.getName());
                Integer value2 = Integer.valueOf(o2.getName());
                return value1- value2;
            }
        });

        //定义目标对象信息
        File targetFile = new File(targetFileName);
        //写入新文件对象定义
        FileOutputStream writeFile = null;//定义空对象，方便关闭

        try {
            //开启目标对象可写入的模式
            writeFile = new FileOutputStream(targetFile);
            //定义每次读取的切片的大小，1次1M
            byte[] bytes = new byte[1024];
            //循环执行临时文件目录对象
            for (int i = 0; i < listFiles.length; i++) {
                //获取文件切片对象 当前切片对象
                File chunkFile = new File(tmpFolder + "/" + i);
                FileInputStream readFile = null;
                try {
                    readFile = new FileInputStream(chunkFile);
                    //判断是否到文件结尾
                    while (readFile.read(bytes) != -1){
                        writeFile.write(bytes,0,bytes.length);
                    }
                }catch (Exception e){
                    log.error("合并分片失败:{}",e.getMessage());
                    throw new Exception("合并分片失败");
                }finally {
                    if(Objects.nonNull(readFile)){
                        readFile.close();
                    }
                }
            }

        }catch (Exception e){
            log.error("合并文件失败:{}",e.getMessage());
            throw new RuntimeException(e.getMessage());
        }finally {
            try {
                if(Objects.nonNull(writeFile)){
                    writeFile.close();
                }
                if(isDel && tmpDir.exists()){
                    FileUtil.del((tmpDir));
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
